#pragma once
#include <functional>
#include <vector>
#include "rule.hpp"
#include "col.hpp"
#include "BPlusTree.h"

using namespace std;
enum IndexType{VR,TV,RB};
//返回的下标组必须排序
//如果操作的是视图，就把查询结果和视图的allSub取交集（返回的还是原表的sub而不是视图表的）


class index
{
protected:
    bool supportMod=false;
    IndexType type;
public:
    virtual vector<char> find(ruleExp* rule)=0;
    col* c; //会直接跟着列变
    index(col* c) : c(c) {type=VR;}

    IndexType getIndexType(){return type;}

    bool isSupportMod() { return this->supportMod; }
    //都是在操作col前调用，如果支持修改下面三个必须都支持
    virtual void add(Basic* v) { throw string("This index does not support updating"); } //和col里的共用一个数据对象，无所有权
    virtual void mod(int opSub, Basic* v) { throw string("This index does not support updating"); }
    virtual void del(int opSub) { throw string("This index does not support updating"); } //因为无所有权，所以不删除数据对象

    virtual ~index() {}
};

class traversalIndex : public index
{
public:
    traversalIndex(col* _c) : index(_c) {this->type=TV;}

    virtual vector<char> find(ruleExp* rule)
    {
        auto data=c->getAllData();
        vector<char> result(data.size(),0);
        for(int i=0;i<data.size();i++)
        {
            Basic* v=data[i];
            if(rule->eval(v))
                result[i]=1;
        }
        return result; //这个本来就是从前到后遍历的，就不用排序了
    }
};

class rbTreeIndex: public index{
private:
    TYPE dataType=_NULL;
    multimap<Basic*,int,less2<Basic*>> rbTree;

public:
    rbTreeIndex(col* c):index(c){
        this->type=RB;
        supportMod=true;
        int index=0;
        for(Basic* b:c->getAllData()){
            TYPE tmpType=b->getType();
            if(tmpType==_NULL){
                index++;
                continue;
            }
            if(dataType==_NULL){
                this->dataType=tmpType;
            }
            else{
                if(this->dataType!=tmpType){
                    throw string("type error");
                }
            }
            rbTree.insert(make_pair(b,index));
            index++;
        }
    }



    virtual void add(Basic *v) override{
        TYPE tmpType=v->getType();
        if(tmpType==_NULL){
            return;
        }
        if(dataType==_NULL){
            dataType=tmpType;
        }
        else if(tmpType!=this->dataType){
            throw string("type mismatch");
        }
        rbTree.insert(make_pair(v,c->getLen()));
    }

    virtual void del(int opSub) override{
        bool flag=false;
        for(auto it=rbTree.begin();it!=rbTree.end();it++){
            if(it->second==opSub){
                rbTree.erase(it);
                flag=true;
                break;
            }
        }
        if(flag==false){
            throw string("The specified subscript was not found");
        }
        for(auto it=rbTree.begin();it!=rbTree.end();it++){
            if(it->second>opSub){
                it->second--;
            }
        }
    }

    virtual void mod(int opSub, Basic *v) override{
        add(v);
        del(opSub);
    }

    virtual vector<char> find(ruleExp *rule) override{
        int colLen=c->getLen();
        return rule->rbTreeSearch(rbTree,dataType,colLen);
    }
};



static index* getCorIndex(col* c,IndexType type){
    if(type==TV){
        return new traversalIndex (c);
    }
    else if(type==RB){
        return new rbTreeIndex(c);
    }
    else{
        throw string("Wrong index type");
    }
}


